/**
 * 
 */
package com.ws.framework.remoteservice.core.util;

import java.util.Iterator;
import java.util.Map.Entry;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.ws.framework.remoteservice.core.model.ConsumerInfo;
import com.ws.framework.remoteservice.core.model.ProviderInfo;
import com.ws.framework.remoteservice.core.model.ServiceKey;

/**
 * @author WSH
 *
 */
public class WsProtocolParser {

	public static String constractEncode(String contractkName, String implCode) {
		return WrsiConstants.Starter + Joiner.on(WrsiConstants.Separator).join(WrsiConstants.Prefix,
				Joiner.on(WrsiConstants.Appender).join(contractkName, implCode));
	}
	
	public static String providerEncode(String contractkName, String implCode, ProviderInfo provider) {
		return Joiner.on(WrsiConstants.Separator).join(providerPrefixEncode(contractkName, implCode), provider);
	}
	
	public static String providerPrefixEncode(String contractkName, String implCode) {
		return Joiner.on(WrsiConstants.Separator).join(constractEncode(contractkName, implCode), WrsiConstants.Provider);
	}
	
	public static String consumerEncode(String contractkName, String implCode, ConsumerInfo consumer) {
		return Joiner.on(WrsiConstants.Separator).join(consumerPrefixEncode(contractkName, implCode), consumer);
	}
	
	public static String consumerPrefixEncode(String contractkName, String implCode) {
		return Joiner.on(WrsiConstants.Separator).join(constractEncode(contractkName, implCode), WrsiConstants.Consumer);
	}
	
	public static Entry<ServiceKey, ProviderInfo> decode(String path)
			throws IllegalStateException, NullPointerException, IllegalArgumentException {
		if (StringUtils.isEmpty(path) || !path.contains(WrsiConstants.Appender) || !path.contains(WrsiConstants.Provider))
			throw new IllegalStateException("Path invalid stat." + path);
		Iterator<String> iterator = Splitter.on(WrsiConstants.Separator).trimResults().split(path).iterator();
		ServiceKey serviceKey = null;
		ProviderInfo info = null;
		while (iterator.hasNext()) {
			String split = iterator.next();
			if (split.contains(WrsiConstants.Appender)) {
				if (split.contains(WrsiConstants.host_port_appender)) {
					info = addressDecode(split);
				} else {
					serviceKey =serviceKeyDecode(split);
				}
			}
		}
		Preconditions.checkNotNull(null != serviceKey && null != info);
		return new EasyEntry<ServiceKey, ProviderInfo>(serviceKey, info);
	}
	
	public static ProviderInfo addressDecode(String path)
			throws IllegalStateException, NullPointerException, IllegalArgumentException {
		if (StringUtils.isEmpty(path) || !path.contains(WrsiConstants.Appender) || !path.contains(WrsiConstants.host_port_appender))
			throw new IllegalStateException("Path invalid stat." + path);
		String schemal = path.substring(0, path.indexOf(WrsiConstants.Appender));
		String host = path.substring(path.indexOf(WrsiConstants.Appender) + 1, path.indexOf(WrsiConstants.host_port_appender));
		int port = Integer.parseInt(path.substring(path.indexOf(WrsiConstants.host_port_appender) + 1));
		ProviderInfo info = new ProviderInfo(schemal, host, port);
		Preconditions.checkNotNull(null != info);
		return info;
	}
	
	public static ServiceKey serviceKeyDecode(String path)
			throws IllegalStateException, NullPointerException, IllegalArgumentException {
		if (StringUtils.isEmpty(path) || !path.contains(WrsiConstants.Appender))
			throw new IllegalStateException("Path invalid stat." + path);
		ServiceKey serviceKey = new ServiceKey(path.substring(0, path.indexOf(WrsiConstants.Appender)),
				path.substring(path.indexOf(WrsiConstants.Appender) + 1));
		Preconditions.checkNotNull(null != serviceKey);
		return serviceKey;
	}

	public static void main(String[] args) {
		ProviderInfo info = new ProviderInfo("TCP", NetUtils.getLocalHost(), 888);
		String path = providerEncode("com.ws.service.MyService", "com.ws.service.impl.MyserviceImpl", info);
		System.out.println(path);
	}

	public static class EasyEntry<K, V> implements Entry<K, V> {
		private K key;

		public EasyEntry(K key, V v) {
			super();
			this.key = key;
			this.v = v;
		}

		private V v;

		@Override
		public K getKey() {
			return key;
		}

		@Override
		public V getValue() {
			return v;
		}

		@Override
		public V setValue(V value) {
			this.v = value;
			return null;
		}

	}
}
